{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "42ed00c1-b5b8-4243-a8f1-c3324fd89339",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-09-29T13:28:01.263449Z",
     "iopub.status.busy": "2024-09-29T13:28:01.263101Z",
     "iopub.status.idle": "2024-09-29T13:28:01.269897Z",
     "shell.execute_reply": "2024-09-29T13:28:01.268485Z",
     "shell.execute_reply.started": "2024-09-29T13:28:01.263420Z"
    }
   },
   "outputs": [],
   "source": [
    "from IPython.display import Image"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "61faecb3-75f9-4b5b-96b0-2936c9d1fb14",
   "metadata": {},
   "source": [
    "- DAG: Directed Acyclic Graph\n",
    "    - 有向无环图；\n",
    "        - 环：means cycle back；\n",
    "    - formalized workflow for transitioning data\n",
    "    - 一个节点可以有多个出边（如下图的节点 `a`），即有多条 outgoing 的路径；\n",
    "        - 自然一个节点也可以有多个入边，如下图的节点 `d`；\n",
    "    - DAG的主要关注点并不是任务内部的运作机制，而是它们应该如何执行，包括执行的顺序、重试逻辑、超时以及其他操作方面的问题。这种抽象使得创建复杂的工作流变得容易管理和监控。\n",
    "        - https://www.51cto.com/article/781996.html\n",
    "- langgraph 比着 DAG 很大的一个改进就是存在循环；"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "07367f35-f509-43b6-b0d0-6eb02d34b3b0",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-09-29T13:29:31.210315Z",
     "iopub.status.busy": "2024-09-29T13:29:31.209681Z",
     "iopub.status.idle": "2024-09-29T13:29:31.221251Z",
     "shell.execute_reply": "2024-09-29T13:29:31.219560Z",
     "shell.execute_reply.started": "2024-09-29T13:29:31.210266Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<img src=\"./imgs/dag.png\" width=\"300\"/>"
      ],
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Image(url='./imgs/dag.png', width=300)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b36203a1-f6a3-4570-9825-1c63d693a233",
   "metadata": {},
   "source": [
    "### prompt template"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c1666685-ad84-40a1-9123-8d5798ecfea9",
   "metadata": {},
   "source": [
    "- https://api.python.langchain.com/en/latest/agents/langchain.agents.react.agent.create_react_agent.html"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "55448ad9-1973-4c19-9cd7-a5e7b3bd0bd5",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-09-22T05:16:55.068892Z",
     "iopub.status.busy": "2024-09-22T05:16:55.067607Z",
     "iopub.status.idle": "2024-09-22T05:16:55.583065Z",
     "shell.execute_reply": "2024-09-22T05:16:55.581576Z",
     "shell.execute_reply.started": "2024-09-22T05:16:55.068828Z"
    }
   },
   "outputs": [],
   "source": [
    "from langchain_core.prompts import PromptTemplate\n",
    "\n",
    "template = '''Answer the following questions as best you can. You have access to the following tools:\n",
    "\n",
    "{tools}\n",
    "\n",
    "Use the following format:\n",
    "\n",
    "Question: the input question you must answer\n",
    "Thought: you should always think about what to do\n",
    "Action: the action to take, should be one of [{tool_names}]\n",
    "Action Input: the input to the action\n",
    "Observation: the result of the action\n",
    "... (this Thought/Action/Action Input/Observation can repeat N times)\n",
    "Thought: I now know the final answer\n",
    "Final Answer: the final answer to the original input question\n",
    "\n",
    "Begin!\n",
    "\n",
    "Question: {input}\n",
    "Thought:{agent_scratchpad}'''\n",
    "\n",
    "prompt = PromptTemplate.from_template(template)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "51b08c02-7670-4f3c-b9da-50e21dba8e1c",
   "metadata": {},
   "source": [
    "### messages"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a9bf2cc0-af46-468c-bdba-85767626af7b",
   "metadata": {},
   "source": [
    "https://python.langchain.com/v0.1/docs/modules/model_io/chat/message_types/\n",
    "\n",
    "- All messages have a role and a content property.\n",
    "    - additional_kwargs\n",
    "        - function_call\n",
    "- message types\n",
    "    - HumanMessage\n",
    "    - AIMessage: role, assistant\n",
    "        - a message from the model.\n",
    "        - additional_kwargs (tool_calls)\n",
    "    - FunctionMessage: role, tool\n",
    "        - represents the result of a function call.\n",
    "        - role, content, name\n",
    "    - ToolMessage: role, tool\n",
    "        - the result of a tool call.\n",
    "        - his is distinct from a FunctionMessage in order to match OpenAI's `function` and `tool` message types. \n",
    "        - role, content, tool_call_id"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "163573dd-d1d6-4585-ae93-960795bdee10",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-09-29T13:29:16.967087Z",
     "iopub.status.busy": "2024-09-29T13:29:16.966762Z",
     "iopub.status.idle": "2024-09-29T13:29:16.977667Z",
     "shell.execute_reply": "2024-09-29T13:29:16.975818Z",
     "shell.execute_reply.started": "2024-09-29T13:29:16.967064Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<img src=\"https://cdn.openai.com/API/docs/images/function-calling-diagram.png\" width=\"500\"/>"
      ],
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# https://platform.openai.com/docs/guides/function-calling\n",
    "Image(url='https://cdn.openai.com/API/docs/images/function-calling-diagram.png', width=500)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "af51fe36-880f-4172-948a-cf4c86852b98",
   "metadata": {},
   "source": [
    "### tool"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "625c498f-f1d1-4a09-a5f9-2f5bebd81ff2",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-10-21T15:27:06.143734Z",
     "iopub.status.busy": "2024-10-21T15:27:06.143352Z",
     "iopub.status.idle": "2024-10-21T15:27:06.152481Z",
     "shell.execute_reply": "2024-10-21T15:27:06.150906Z",
     "shell.execute_reply.started": "2024-10-21T15:27:06.143705Z"
    }
   },
   "outputs": [],
   "source": [
    "import openai\n",
    "from openai import OpenAI\n",
    "from dotenv import load_dotenv\n",
    "assert load_dotenv()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "07006845-7585-4259-b71a-705e12994acc",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-10-21T15:28:42.180460Z",
     "iopub.status.busy": "2024-10-21T15:28:42.179828Z",
     "iopub.status.idle": "2024-10-21T15:28:43.494475Z",
     "shell.execute_reply": "2024-10-21T15:28:43.492264Z",
     "shell.execute_reply.started": "2024-10-21T15:28:42.180408Z"
    }
   },
   "outputs": [],
   "source": [
    "tools = [\n",
    "    {\n",
    "        \"type\": \"function\",\n",
    "        \"function\": {\n",
    "            \"name\": \"get_delivery_date\",\n",
    "            \"description\": \"Get the delivery date for a customer's order. Call this whenever you need to know the delivery date, for example when a customer asks 'Where is my package'\",\n",
    "            \"parameters\": {\n",
    "                \"type\": \"object\",\n",
    "                \"properties\": {\n",
    "                    \"order_id\": {\n",
    "                        \"type\": \"string\",\n",
    "                        \"description\": \"The customer's order ID.\"\n",
    "                    }\n",
    "                },\n",
    "                \"required\": [\"order_id\"],\n",
    "                \"additionalProperties\": False\n",
    "            }\n",
    "        }\n",
    "    }\n",
    "]\n",
    "\n",
    "messages = []\n",
    "messages.append({\"role\": \"system\", \"content\": \"You are a helpful customer support assistant. Use the supplied tools to assist the user.\"})\n",
    "messages.append({\"role\": \"user\", \"content\": \"Hi, can you tell me the delivery date for my order?\"})\n",
    "messages.append({\"role\": \"assistant\", \"content\": \"Hi there! I can help with that. Can you please provide your order ID?\"})\n",
    "messages.append({\"role\": \"user\", \"content\": \"i think it is order_12345\"})\n",
    "\n",
    "client = OpenAI()\n",
    "\n",
    "response = client.chat.completions.create(\n",
    "    model='gpt-4o',\n",
    "    messages=messages,\n",
    "    tools=tools\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "bd065248-bbda-4457-9532-81440306f3a5",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-10-21T15:28:45.839800Z",
     "iopub.status.busy": "2024-10-21T15:28:45.839185Z",
     "iopub.status.idle": "2024-10-21T15:28:45.869983Z",
     "shell.execute_reply": "2024-10-21T15:28:45.868079Z",
     "shell.execute_reply.started": "2024-10-21T15:28:45.839750Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #800080; text-decoration-color: #800080; font-weight: bold\">ChatCompletion</span><span style=\"font-weight: bold\">(</span>\n",
       "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   </span><span style=\"color: #808000; text-decoration-color: #808000\">id</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'chatcmpl-AKocl6OsGRjymYnNY3yhjCITCtujQ'</span>,\n",
       "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   </span><span style=\"color: #808000; text-decoration-color: #808000\">choices</span>=<span style=\"font-weight: bold\">[</span>\n",
       "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   </span><span style=\"color: #800080; text-decoration-color: #800080; font-weight: bold\">Choice</span><span style=\"font-weight: bold\">(</span>\n",
       "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   │   </span><span style=\"color: #808000; text-decoration-color: #808000\">finish_reason</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'tool_calls'</span>,\n",
       "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   │   </span><span style=\"color: #808000; text-decoration-color: #808000\">index</span>=<span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0</span>,\n",
       "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   │   </span><span style=\"color: #808000; text-decoration-color: #808000\">logprobs</span>=<span style=\"color: #800080; text-decoration-color: #800080; font-style: italic\">None</span>,\n",
       "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   │   </span><span style=\"color: #808000; text-decoration-color: #808000\">message</span>=<span style=\"color: #800080; text-decoration-color: #800080; font-weight: bold\">ChatCompletionMessage</span><span style=\"font-weight: bold\">(</span>\n",
       "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   │   │   </span><span style=\"color: #808000; text-decoration-color: #808000\">content</span>=<span style=\"color: #800080; text-decoration-color: #800080; font-style: italic\">None</span>,\n",
       "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   │   │   </span><span style=\"color: #808000; text-decoration-color: #808000\">refusal</span>=<span style=\"color: #800080; text-decoration-color: #800080; font-style: italic\">None</span>,\n",
       "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   │   │   </span><span style=\"color: #808000; text-decoration-color: #808000\">role</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'assistant'</span>,\n",
       "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   │   │   </span><span style=\"color: #808000; text-decoration-color: #808000\">function_call</span>=<span style=\"color: #800080; text-decoration-color: #800080; font-style: italic\">None</span>,\n",
       "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   │   │   </span><span style=\"color: #808000; text-decoration-color: #808000\">tool_calls</span>=<span style=\"font-weight: bold\">[</span>\n",
       "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   │   │   │   </span><span style=\"color: #800080; text-decoration-color: #800080; font-weight: bold\">ChatCompletionMessageToolCall</span><span style=\"font-weight: bold\">(</span>\n",
       "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   │   │   │   │   </span><span style=\"color: #808000; text-decoration-color: #808000\">id</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'call_ANhZc0ZbbwDLLgTYA9ZQadRH'</span>,\n",
       "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   │   │   │   │   </span><span style=\"color: #808000; text-decoration-color: #808000\">function</span>=<span style=\"color: #800080; text-decoration-color: #800080; font-weight: bold\">Function</span><span style=\"font-weight: bold\">(</span><span style=\"color: #808000; text-decoration-color: #808000\">arguments</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'{\"order_id\":\"order_12345\"}'</span>, <span style=\"color: #808000; text-decoration-color: #808000\">name</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'get_delivery_date'</span><span style=\"font-weight: bold\">)</span>,\n",
       "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   │   │   │   │   </span><span style=\"color: #808000; text-decoration-color: #808000\">type</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'function'</span>\n",
       "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   │   │   │   </span><span style=\"font-weight: bold\">)</span>\n",
       "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   │   │   </span><span style=\"font-weight: bold\">]</span>\n",
       "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   │   </span><span style=\"font-weight: bold\">)</span>\n",
       "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   </span><span style=\"font-weight: bold\">)</span>\n",
       "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   </span><span style=\"font-weight: bold\">]</span>,\n",
       "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   </span><span style=\"color: #808000; text-decoration-color: #808000\">created</span>=<span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">1729524523</span>,\n",
       "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   </span><span style=\"color: #808000; text-decoration-color: #808000\">model</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'gpt-4o-2024-08-06'</span>,\n",
       "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   </span><span style=\"color: #808000; text-decoration-color: #808000\">object</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'chat.completion'</span>,\n",
       "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   </span><span style=\"color: #808000; text-decoration-color: #808000\">service_tier</span>=<span style=\"color: #800080; text-decoration-color: #800080; font-style: italic\">None</span>,\n",
       "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   </span><span style=\"color: #808000; text-decoration-color: #808000\">system_fingerprint</span>=<span style=\"color: #008000; text-decoration-color: #008000\">'fp_45c6de4934'</span>,\n",
       "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   </span><span style=\"color: #808000; text-decoration-color: #808000\">usage</span>=<span style=\"color: #800080; text-decoration-color: #800080; font-weight: bold\">CompletionUsage</span><span style=\"font-weight: bold\">(</span>\n",
       "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   </span><span style=\"color: #808000; text-decoration-color: #808000\">completion_tokens</span>=<span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">19</span>,\n",
       "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   </span><span style=\"color: #808000; text-decoration-color: #808000\">prompt_tokens</span>=<span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">140</span>,\n",
       "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   </span><span style=\"color: #808000; text-decoration-color: #808000\">total_tokens</span>=<span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">159</span>,\n",
       "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   </span><span style=\"color: #808000; text-decoration-color: #808000\">prompt_tokens_details</span>=<span style=\"font-weight: bold\">{</span><span style=\"color: #008000; text-decoration-color: #008000\">'cached_tokens'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0</span><span style=\"font-weight: bold\">}</span>,\n",
       "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   │   </span><span style=\"color: #808000; text-decoration-color: #808000\">completion_tokens_details</span>=<span style=\"font-weight: bold\">{</span><span style=\"color: #008000; text-decoration-color: #008000\">'reasoning_tokens'</span>: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0</span><span style=\"font-weight: bold\">}</span>\n",
       "<span style=\"color: #7fbf7f; text-decoration-color: #7fbf7f\">│   </span><span style=\"font-weight: bold\">)</span>\n",
       "<span style=\"font-weight: bold\">)</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[1;35mChatCompletion\u001b[0m\u001b[1m(\u001b[0m\n",
       "\u001b[2;32m│   \u001b[0m\u001b[33mid\u001b[0m=\u001b[32m'chatcmpl-AKocl6OsGRjymYnNY3yhjCITCtujQ'\u001b[0m,\n",
       "\u001b[2;32m│   \u001b[0m\u001b[33mchoices\u001b[0m=\u001b[1m[\u001b[0m\n",
       "\u001b[2;32m│   │   \u001b[0m\u001b[1;35mChoice\u001b[0m\u001b[1m(\u001b[0m\n",
       "\u001b[2;32m│   │   │   \u001b[0m\u001b[33mfinish_reason\u001b[0m=\u001b[32m'tool_calls'\u001b[0m,\n",
       "\u001b[2;32m│   │   │   \u001b[0m\u001b[33mindex\u001b[0m=\u001b[1;36m0\u001b[0m,\n",
       "\u001b[2;32m│   │   │   \u001b[0m\u001b[33mlogprobs\u001b[0m=\u001b[3;35mNone\u001b[0m,\n",
       "\u001b[2;32m│   │   │   \u001b[0m\u001b[33mmessage\u001b[0m=\u001b[1;35mChatCompletionMessage\u001b[0m\u001b[1m(\u001b[0m\n",
       "\u001b[2;32m│   │   │   │   \u001b[0m\u001b[33mcontent\u001b[0m=\u001b[3;35mNone\u001b[0m,\n",
       "\u001b[2;32m│   │   │   │   \u001b[0m\u001b[33mrefusal\u001b[0m=\u001b[3;35mNone\u001b[0m,\n",
       "\u001b[2;32m│   │   │   │   \u001b[0m\u001b[33mrole\u001b[0m=\u001b[32m'assistant'\u001b[0m,\n",
       "\u001b[2;32m│   │   │   │   \u001b[0m\u001b[33mfunction_call\u001b[0m=\u001b[3;35mNone\u001b[0m,\n",
       "\u001b[2;32m│   │   │   │   \u001b[0m\u001b[33mtool_calls\u001b[0m=\u001b[1m[\u001b[0m\n",
       "\u001b[2;32m│   │   │   │   │   \u001b[0m\u001b[1;35mChatCompletionMessageToolCall\u001b[0m\u001b[1m(\u001b[0m\n",
       "\u001b[2;32m│   │   │   │   │   │   \u001b[0m\u001b[33mid\u001b[0m=\u001b[32m'call_ANhZc0ZbbwDLLgTYA9ZQadRH'\u001b[0m,\n",
       "\u001b[2;32m│   │   │   │   │   │   \u001b[0m\u001b[33mfunction\u001b[0m=\u001b[1;35mFunction\u001b[0m\u001b[1m(\u001b[0m\u001b[33marguments\u001b[0m=\u001b[32m'\u001b[0m\u001b[32m{\u001b[0m\u001b[32m\"order_id\":\"order_12345\"\u001b[0m\u001b[32m}\u001b[0m\u001b[32m'\u001b[0m, \u001b[33mname\u001b[0m=\u001b[32m'get_delivery_date'\u001b[0m\u001b[1m)\u001b[0m,\n",
       "\u001b[2;32m│   │   │   │   │   │   \u001b[0m\u001b[33mtype\u001b[0m=\u001b[32m'function'\u001b[0m\n",
       "\u001b[2;32m│   │   │   │   │   \u001b[0m\u001b[1m)\u001b[0m\n",
       "\u001b[2;32m│   │   │   │   \u001b[0m\u001b[1m]\u001b[0m\n",
       "\u001b[2;32m│   │   │   \u001b[0m\u001b[1m)\u001b[0m\n",
       "\u001b[2;32m│   │   \u001b[0m\u001b[1m)\u001b[0m\n",
       "\u001b[2;32m│   \u001b[0m\u001b[1m]\u001b[0m,\n",
       "\u001b[2;32m│   \u001b[0m\u001b[33mcreated\u001b[0m=\u001b[1;36m1729524523\u001b[0m,\n",
       "\u001b[2;32m│   \u001b[0m\u001b[33mmodel\u001b[0m=\u001b[32m'gpt-4o-2024-08-06'\u001b[0m,\n",
       "\u001b[2;32m│   \u001b[0m\u001b[33mobject\u001b[0m=\u001b[32m'chat.completion'\u001b[0m,\n",
       "\u001b[2;32m│   \u001b[0m\u001b[33mservice_tier\u001b[0m=\u001b[3;35mNone\u001b[0m,\n",
       "\u001b[2;32m│   \u001b[0m\u001b[33msystem_fingerprint\u001b[0m=\u001b[32m'fp_45c6de4934'\u001b[0m,\n",
       "\u001b[2;32m│   \u001b[0m\u001b[33musage\u001b[0m=\u001b[1;35mCompletionUsage\u001b[0m\u001b[1m(\u001b[0m\n",
       "\u001b[2;32m│   │   \u001b[0m\u001b[33mcompletion_tokens\u001b[0m=\u001b[1;36m19\u001b[0m,\n",
       "\u001b[2;32m│   │   \u001b[0m\u001b[33mprompt_tokens\u001b[0m=\u001b[1;36m140\u001b[0m,\n",
       "\u001b[2;32m│   │   \u001b[0m\u001b[33mtotal_tokens\u001b[0m=\u001b[1;36m159\u001b[0m,\n",
       "\u001b[2;32m│   │   \u001b[0m\u001b[33mprompt_tokens_details\u001b[0m=\u001b[1m{\u001b[0m\u001b[32m'cached_tokens'\u001b[0m: \u001b[1;36m0\u001b[0m\u001b[1m}\u001b[0m,\n",
       "\u001b[2;32m│   │   \u001b[0m\u001b[33mcompletion_tokens_details\u001b[0m=\u001b[1m{\u001b[0m\u001b[32m'reasoning_tokens'\u001b[0m: \u001b[1;36m0\u001b[0m\u001b[1m}\u001b[0m\n",
       "\u001b[2;32m│   \u001b[0m\u001b[1m)\u001b[0m\n",
       "\u001b[1m)\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from rich.pretty import pprint\n",
    "pprint(response)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f2e365bf-1e51-415e-8e64-bf8b7dd432d9",
   "metadata": {},
   "source": [
    "\n",
    "- llm 的 invoke 本身也可以作为 tool\n",
    "\n",
    "    ```\n",
    "    @tool\n",
    "    def translate(string: str) -> str:\n",
    "        \"\"\"Translate the string into Chinese.\"\"\"\n",
    "        # model: BaseOpenAI = OpenAI(openai_api_key=OPENAI_API_KEY, temperature=0)\n",
    "        # res = model.predict(f\"Translate {string} into Chinese, only return the result.\")\n",
    "        # return res.strip()\n",
    "        chat_template = ChatPromptTemplate.from_messages(\n",
    "            [\n",
    "                (\n",
    "                    \"system\",\n",
    "                    \"\"\"You're an translator to translate text into Chinese, only return the result.\n",
    "                    \"\"\",\n",
    "                ),\n",
    "                (\n",
    "                    \"human\",\n",
    "                    string,\n",
    "                ),\n",
    "            ]\n",
    "        )\n",
    "        llm = Ollama(\n",
    "            base_url=\"http://localhost:11434\",\n",
    "            model=\"gemma:2b-instruct\",\n",
    "            temperature=0.0,\n",
    "        )\n",
    "    \n",
    "        return (chat_template | llm | StrOutputParser()).invoke({\"string\": string})\n",
    "    ```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4462c248-80e4-4636-bb32-d5b778867097",
   "metadata": {},
   "source": [
    "### lcel"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "2f8db8f9-a8f7-410c-8718-91cb6d1578e0",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-09-25T14:56:17.540081Z",
     "iopub.status.busy": "2024-09-25T14:56:17.539465Z",
     "iopub.status.idle": "2024-09-25T14:56:17.564812Z",
     "shell.execute_reply": "2024-09-25T14:56:17.562926Z",
     "shell.execute_reply.started": "2024-09-25T14:56:17.540024Z"
    }
   },
   "outputs": [],
   "source": [
    "from dotenv import load_dotenv\n",
    "assert load_dotenv()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "0c5954e7-3e66-48a0-905a-5e80aa2062d5",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-09-25T14:56:20.642865Z",
     "iopub.status.busy": "2024-09-25T14:56:20.642283Z",
     "iopub.status.idle": "2024-09-25T14:56:21.993080Z",
     "shell.execute_reply": "2024-09-25T14:56:21.991477Z",
     "shell.execute_reply.started": "2024-09-25T14:56:20.642811Z"
    }
   },
   "outputs": [],
   "source": [
    "from langchain_openai import ChatOpenAI\n",
    "\n",
    "model = ChatOpenAI(model=\"gpt-3.5-turbo\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "fbcfa138-c92f-4020-801f-5e1ea67e6591",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-09-25T14:58:15.052552Z",
     "iopub.status.busy": "2024-09-25T14:58:15.051943Z",
     "iopub.status.idle": "2024-09-25T14:58:15.062125Z",
     "shell.execute_reply": "2024-09-25T14:58:15.060149Z",
     "shell.execute_reply.started": "2024-09-25T14:58:15.052503Z"
    }
   },
   "outputs": [],
   "source": [
    "from langchain_core.output_parsers import StrOutputParser\n",
    "from langchain_core.prompts import ChatPromptTemplate\n",
    "\n",
    "prompt = ChatPromptTemplate.from_template(\"tell me a short joke about {topic}\")\n",
    "output_parser = StrOutputParser()\n",
    "\n",
    "chain = prompt | model | output_parser"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "aa5fba88-fac0-4150-9ac4-de678eb4b835",
   "metadata": {},
   "source": [
    "- StrOutputParser(): 作用的对象是 Message"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "a10208ea-d1ed-4fdb-9a78-b1c373c31a26",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-09-25T14:56:55.985530Z",
     "iopub.status.busy": "2024-09-25T14:56:55.984952Z",
     "iopub.status.idle": "2024-09-25T14:56:57.194042Z",
     "shell.execute_reply": "2024-09-25T14:56:57.191990Z",
     "shell.execute_reply.started": "2024-09-25T14:56:55.985483Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Why did the pig go to the casino? Because he heard they had a lot of \"squeal\" machines!'"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "chain.invoke({'topic': 'pig'})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "2d583439-b46f-4006-8bd1-86ce8eb17e24",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-09-25T14:58:18.335646Z",
     "iopub.status.busy": "2024-09-25T14:58:18.335057Z",
     "iopub.status.idle": "2024-09-25T14:58:18.351620Z",
     "shell.execute_reply": "2024-09-25T14:58:18.349992Z",
     "shell.execute_reply.started": "2024-09-25T14:58:18.335596Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "ChatPromptValue(messages=[HumanMessage(content='tell me a short joke about pig', additional_kwargs={}, response_metadata={})])"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "chain.first.invoke({'topic': 'pig'})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "46f19d7b-54f9-4d03-a9b2-0004161b74e1",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-09-25T14:57:35.589612Z",
     "iopub.status.busy": "2024-09-25T14:57:35.589016Z",
     "iopub.status.idle": "2024-09-25T14:57:35.599461Z",
     "shell.execute_reply": "2024-09-25T14:57:35.597233Z",
     "shell.execute_reply.started": "2024-09-25T14:57:35.589557Z"
    }
   },
   "outputs": [],
   "source": [
    "from langchain_core.prompts import PromptTemplate\n",
    "prompt = PromptTemplate.from_template(\"tell me a short joke about {topic}\")\n",
    "output_parser = StrOutputParser()\n",
    "\n",
    "chain = prompt | model | output_parser"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "734ad2eb-94c3-476f-a387-67e3d7eb6e78",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-09-25T14:57:39.896041Z",
     "iopub.status.busy": "2024-09-25T14:57:39.895461Z",
     "iopub.status.idle": "2024-09-25T14:57:40.911193Z",
     "shell.execute_reply": "2024-09-25T14:57:40.909252Z",
     "shell.execute_reply.started": "2024-09-25T14:57:39.895989Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Why did the pig go to the casino? He heard they had a lot of bacon!'"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "chain.invoke({'topic': 'pig'})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "1d9c3174-b3ce-4791-8759-a05b5fafc21c",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-09-25T14:58:07.444538Z",
     "iopub.status.busy": "2024-09-25T14:58:07.444250Z",
     "iopub.status.idle": "2024-09-25T14:58:07.455517Z",
     "shell.execute_reply": "2024-09-25T14:58:07.453585Z",
     "shell.execute_reply.started": "2024-09-25T14:58:07.444516Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "StringPromptValue(text='tell me a short joke about pig')"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "chain.first.invoke({'topic': 'pig'})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "0351c1aa-03b9-45a7-a735-fba02201e7d7",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-09-25T14:59:50.222953Z",
     "iopub.status.busy": "2024-09-25T14:59:50.222348Z",
     "iopub.status.idle": "2024-09-25T14:59:50.232969Z",
     "shell.execute_reply": "2024-09-25T14:59:50.230947Z",
     "shell.execute_reply.started": "2024-09-25T14:59:50.222903Z"
    }
   },
   "outputs": [],
   "source": [
    "prompt = PromptTemplate.from_template(\"tell me a short joke about {topic}\")\n",
    "output_parser = StrOutputParser()\n",
    "\n",
    "chain = prompt | (lambda x: x.text) | model | output_parser"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "d01ff505-391b-459b-974c-1d546ac613c2",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-09-25T14:59:57.403214Z",
     "iopub.status.busy": "2024-09-25T14:59:57.402627Z",
     "iopub.status.idle": "2024-09-25T14:59:58.737553Z",
     "shell.execute_reply": "2024-09-25T14:59:58.735511Z",
     "shell.execute_reply.started": "2024-09-25T14:59:57.403164Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Why did the pig go to the kitchen? Because he felt like bacon!'"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "chain.invoke({'topic': 'pig'})"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e4b8b8f2-7ae3-4a7b-875a-7e6561638e2e",
   "metadata": {},
   "source": [
    "#### members"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "13086b0c-28b5-4e55-bb8e-fa1434172c18",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-09-22T05:16:56.152013Z",
     "iopub.status.busy": "2024-09-22T05:16:56.151815Z",
     "iopub.status.idle": "2024-09-22T05:16:56.170399Z",
     "shell.execute_reply": "2024-09-22T05:16:56.169699Z",
     "shell.execute_reply.started": "2024-09-22T05:16:56.151995Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "ChatPromptTemplate(input_variables=['topic'], messages=[HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['topic'], template='tell me a short joke about {topic}'))])"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "chain.first"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "5313e2be-e65f-47df-9a3e-b9d0ed6bd37a",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-09-22T05:16:56.171253Z",
     "iopub.status.busy": "2024-09-22T05:16:56.171067Z",
     "iopub.status.idle": "2024-09-22T05:16:56.189826Z",
     "shell.execute_reply": "2024-09-22T05:16:56.188954Z",
     "shell.execute_reply.started": "2024-09-22T05:16:56.171236Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "ChatPromptValue(messages=[HumanMessage(content='tell me a short joke about apple')])"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "chain.first.invoke({'topic': 'apple'})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "45c9e7d2-f071-4540-8c23-9fde0acd7ec4",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-09-22T05:16:56.190918Z",
     "iopub.status.busy": "2024-09-22T05:16:56.190719Z",
     "iopub.status.idle": "2024-09-22T05:16:56.198060Z",
     "shell.execute_reply": "2024-09-22T05:16:56.197046Z",
     "shell.execute_reply.started": "2024-09-22T05:16:56.190901Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[HumanMessage(content='tell me a short joke about apple')]"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "chain.first.invoke({'topic': 'apple'}).to_messages()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "dea12368-d8ac-44f6-837b-100f568f1f78",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-09-22T05:16:56.198999Z",
     "iopub.status.busy": "2024-09-22T05:16:56.198807Z",
     "iopub.status.idle": "2024-09-22T05:16:56.205835Z",
     "shell.execute_reply": "2024-09-22T05:16:56.205181Z",
     "shell.execute_reply.started": "2024-09-22T05:16:56.198982Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[ChatOpenAI(client=<openai.resources.chat.completions.Completions object at 0x7fb4fb882330>, async_client=<openai.resources.chat.completions.AsyncCompletions object at 0x7fb4fb883c80>, openai_api_key=SecretStr('**********'), openai_proxy='')]"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "chain.middle"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "96480825-7cbe-4478-8d6e-64844bc76ae8",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-09-22T05:16:56.206739Z",
     "iopub.status.busy": "2024-09-22T05:16:56.206561Z",
     "iopub.status.idle": "2024-09-22T05:16:57.517396Z",
     "shell.execute_reply": "2024-09-22T05:16:57.516262Z",
     "shell.execute_reply.started": "2024-09-22T05:16:56.206723Z"
    }
   },
   "outputs": [],
   "source": [
    "res = chain.middle[0].invoke(chain.first.invoke({'topic': 'math'}))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "51ed1e16-b12c-4fb5-a824-4b5778fbe350",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-09-22T05:16:57.518622Z",
     "iopub.status.busy": "2024-09-22T05:16:57.518315Z",
     "iopub.status.idle": "2024-09-22T05:16:57.525059Z",
     "shell.execute_reply": "2024-09-22T05:16:57.524351Z",
     "shell.execute_reply.started": "2024-09-22T05:16:57.518598Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "AIMessage(content=\"Why was the equal sign so humble?\\n\\nBecause he knew he wasn't less than or greater than anyone else.\", response_metadata={'token_usage': {'completion_tokens': 22, 'prompt_tokens': 14, 'total_tokens': 36, 'completion_tokens_details': {'reasoning_tokens': 0}}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-9823590f-d239-4bce-bb18-5075dccc56ee-0', usage_metadata={'input_tokens': 14, 'output_tokens': 22, 'total_tokens': 36})"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "2a37a4e6-c7d4-4d54-b39d-483fbd0d4537",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-09-22T05:16:57.526112Z",
     "iopub.status.busy": "2024-09-22T05:16:57.525879Z",
     "iopub.status.idle": "2024-09-22T05:16:57.544163Z",
     "shell.execute_reply": "2024-09-22T05:16:57.543150Z",
     "shell.execute_reply.started": "2024-09-22T05:16:57.526089Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "StrOutputParser()"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "chain.last"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "3c1a6780-280e-4a93-82f5-4ad36982bc07",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-09-22T05:16:57.546163Z",
     "iopub.status.busy": "2024-09-22T05:16:57.545663Z",
     "iopub.status.idle": "2024-09-22T05:16:57.566837Z",
     "shell.execute_reply": "2024-09-22T05:16:57.565328Z",
     "shell.execute_reply.started": "2024-09-22T05:16:57.546118Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"Why was the equal sign so humble?\\n\\nBecause he knew he wasn't less than or greater than anyone else.\""
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "chain.last.invoke(res)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "52c94569-f684-4177-a2c1-4632c83200f7",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-09-22T05:16:57.569015Z",
     "iopub.status.busy": "2024-09-22T05:16:57.568507Z",
     "iopub.status.idle": "2024-09-22T05:16:57.589231Z",
     "shell.execute_reply": "2024-09-22T05:16:57.588199Z",
     "shell.execute_reply.started": "2024-09-22T05:16:57.568968Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'tell me a short joke about apple'"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "chain.last.invoke(chain.first.invoke({'topic': 'apple'}).messages[0])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8f0e39a4-94f2-413d-aa0d-37817151ee26",
   "metadata": {},
   "source": [
    "#### create_react_agent"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "102dc0a7-490e-4c95-be03-eeb36b00767b",
   "metadata": {},
   "source": [
    "```\n",
    "prompt = prompt.partial(\n",
    "    tools=tools_renderer(list(tools)),\n",
    "    tool_names=\", \".join([t.name for t in tools]),\n",
    ")\n",
    "\n",
    "if stop_sequence:\n",
    "    stop = [\"\\nObservation\"] if stop_sequence is True else stop_sequence\n",
    "    llm_with_stop = llm.bind(stop=stop)\n",
    "else:\n",
    "    llm_with_stop = llm\n",
    "\n",
    "output_parser = output_parser or ReActSingleInputOutputParser()\n",
    "\n",
    "\n",
    "agent = (\n",
    "    RunnablePassthrough.assign(\n",
    "        agent_scratchpad=lambda x: format_log_to_str(x[\"intermediate_steps\"]),\n",
    "    )\n",
    "    | prompt\n",
    "    | llm_with_stop\n",
    "    | output_parser\n",
    ")\n",
    "\n",
    "return agent\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "304a0da0-1d7f-4824-8745-35114490df14",
   "metadata": {},
   "source": [
    "#### RAG chain "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "86c08019-15dc-4d1c-8a71-cc147ee97f9f",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-09-22T05:10:42.853559Z",
     "iopub.status.busy": "2024-09-22T05:10:42.852915Z",
     "iopub.status.idle": "2024-09-22T05:10:42.864647Z",
     "shell.execute_reply": "2024-09-22T05:10:42.862604Z",
     "shell.execute_reply.started": "2024-09-22T05:10:42.853508Z"
    }
   },
   "source": [
    "```mermaid\n",
    "graph LR\n",
    "    Question --> RunnableParallel\n",
    "    RunnableParallel --> |Question| Retriever\n",
    "    RunnableParallel --> |Question| RunnablePassThrough\n",
    "    Retriever --> |context-retrieved docs| PromptTemplate\n",
    "    RunnablePassThrough --> |question=Question| PromptTemplate\n",
    "    PromptTemplate --> |PromptValue| ChatModel\n",
    "    ChatModel --> |ChatMessage| StrOutputParser\n",
    "    StrOutputParser --> |String| Result\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "449711aa-0894-40f4-b4ab-bd60ae807663",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-09-22T05:16:57.591145Z",
     "iopub.status.busy": "2024-09-22T05:16:57.590704Z",
     "iopub.status.idle": "2024-09-22T05:17:00.930970Z",
     "shell.execute_reply": "2024-09-22T05:17:00.929886Z",
     "shell.execute_reply.started": "2024-09-22T05:16:57.591104Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/whaow/anaconda3/envs/agent/lib/python3.12/site-packages/pydantic/_migration.py:283: UserWarning: `pydantic.error_wrappers:ValidationError` has been moved to `pydantic:ValidationError`.\n",
      "  warnings.warn(f'`{import_path}` has been moved to `{new_location}`.')\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'Harrison worked at Kensho.'"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from langchain_community.vectorstores import DocArrayInMemorySearch\n",
    "from langchain_core.output_parsers import StrOutputParser\n",
    "from langchain_core.prompts import ChatPromptTemplate\n",
    "from langchain_core.runnables import RunnableParallel, RunnablePassthrough\n",
    "from langchain_openai import OpenAIEmbeddings\n",
    "\n",
    "vectorstore = DocArrayInMemorySearch.from_texts(\n",
    "    [\"harrison worked at kensho\", \"bears like to eat honey\"],\n",
    "    embedding=OpenAIEmbeddings(),\n",
    ")\n",
    "retriever = vectorstore.as_retriever()\n",
    "\n",
    "template = \"\"\"Answer the question based only on the following context:\n",
    "{context}\n",
    "\n",
    "Question: {question}\n",
    "\"\"\"\n",
    "prompt = ChatPromptTemplate.from_template(template)\n",
    "output_parser = StrOutputParser()\n",
    "\n",
    "# two branch\n",
    "setup_and_retrieval = RunnableParallel(\n",
    "    {\"context\": retriever, \"question\": RunnablePassthrough()}\n",
    ")\n",
    "chain = setup_and_retrieval | prompt | model | output_parser\n",
    "\n",
    "chain.invoke(\"where did harrison work?\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "408c92d1-19a6-4a49-afbe-a7906de41c99",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-09-22T05:17:00.933304Z",
     "iopub.status.busy": "2024-09-22T05:17:00.932631Z",
     "iopub.status.idle": "2024-09-22T05:17:01.643862Z",
     "shell.execute_reply": "2024-09-22T05:17:01.642789Z",
     "shell.execute_reply.started": "2024-09-22T05:17:00.933255Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'context': [Document(page_content='harrison worked at kensho'),\n",
       "  Document(page_content='bears like to eat honey')],\n",
       " 'question': 'where did harrison work?'}"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "setup_and_retrieval.invoke(\"where did harrison work?\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "465a26b0-6427-4da8-9de8-5c65cb35ad0e",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-09-22T05:17:01.646265Z",
     "iopub.status.busy": "2024-09-22T05:17:01.645581Z",
     "iopub.status.idle": "2024-09-22T05:17:02.041069Z",
     "shell.execute_reply": "2024-09-22T05:17:02.040033Z",
     "shell.execute_reply.started": "2024-09-22T05:17:01.646215Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "ChatPromptValue(messages=[HumanMessage(content=\"Answer the question based only on the following context:\\n[Document(page_content='harrison worked at kensho'), Document(page_content='bears like to eat honey')]\\n\\nQuestion: where did harrison work?\\n\")])"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "prompt.invoke(setup_and_retrieval.invoke(\"where did harrison work?\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "11a6a5ec-e7ab-462c-9380-47608d422c34",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-09-22T05:17:02.043282Z",
     "iopub.status.busy": "2024-09-22T05:17:02.042656Z",
     "iopub.status.idle": "2024-09-22T05:17:03.151000Z",
     "shell.execute_reply": "2024-09-22T05:17:03.148840Z",
     "shell.execute_reply.started": "2024-09-22T05:17:02.043235Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "AIMessage(content='Harrison worked at Kensho.', response_metadata={'token_usage': {'completion_tokens': 7, 'prompt_tokens': 50, 'total_tokens': 57, 'completion_tokens_details': {'reasoning_tokens': 0}}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-398933d0-e643-402f-9c41-ee440b66f642-0', usage_metadata={'input_tokens': 50, 'output_tokens': 7, 'total_tokens': 57})"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model.invoke(prompt.invoke(setup_and_retrieval.invoke(\"where did harrison work?\")))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4941f052-5f89-4cef-83d5-a7c8b9ffd5bc",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "agent",
   "language": "python",
   "name": "agent"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
